package com.testing.sqlUtil;

import java.sql.*;
import java.util.*;

/**
 * @Classname MysqlUtils
 * @Description 类型说明
 * @Date 2021/1/4 21:19
 * @Created by 勾勾
 */
public class MysqlUtils {

    //连接的成员变量，后面的方法都会使用这个创建的连接
    private Connection myConnector;

    //可以通过构造方法来完成连接的建立
    //也可以自己写一个方法来完成连接的建立，完成对myConnection的实例化操作
    //建立连接（通用的方法）
    public void createConnector(){
        try {
            Properties ggP=new Properties();
            //加载:读取resources中的文件内容
            ggP.load(MysqlUtils.class.getResourceAsStream("/login.properties"));
            //拿取数据
            String jdbcUrl=ggP.getProperty("jdbcUrl");
            String username=ggP.getProperty("username");
            String classname=ggP.getProperty("driverClass");
            String password=ggP.getProperty("password");

            Class.forName(classname);
            myConnector= DriverManager.getConnection(jdbcUrl,username,password);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("mysql数据库连接失败");
        }
    }
    /**
     * 核心方法：3
     * 通过输入用户名和密码检查数据库中是否能查询到数据，能查询到登录成功，返回true
     * 不能，登录失败 返回false
     * @param user
     * @param pwd
     */
    public boolean checkLogin(String user,String pwd){

        ResultSet resultSet = null;
        try {
            //3.创建查询
            Statement ggStatement = myConnector.createStatement();
            //4.编写查询语句
            String sql="select * from userinfo where username='"+user+"' and pwd='"+pwd+"'";
            //5.执行查询 得到结果集resultSet
            resultSet = ggStatement.executeQuery(sql);

            //使用短路逻辑运算符，如果resultSet为空，就不会执行resultSet.next(),不会出现空指针异常
            //如果查到数据则说明登录成功，返回true
            if(resultSet!=null&&resultSet.next()){
                return true;
            }
            //否则登录失败，返回false
            else{
                return false;
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return false;
        }
    }

    /**
     * SQL注入问题：
     * 用户名输入a' or 1=1#    密码123
     * String sql="select * from userinfo where username='a' or 1=1#' and pwd='123'";
     * 在SQL语句中#是注释符，所以后面的语句都会被注释掉，那么上面的语句就等价于：
     * String sql="select * from userinfo where username='a' or 1=1
     * 在SQL语句中where相当于判断语句，并且是由 or 连接的，所以 username='a' 和 1=1 中有一个为真就为真。1=1一定为真，所以语句又等价于：
     * String sql="select * from userinfo
     * 这个语句的作用是爆出表中所有字段。
     * 也就是说可以用 a' or 1=1# 这么一个字符串就可以绕开登陆的密码，直接进入程序。
     *
     *
     * call login('a' or 1=1#','123');
     */



    /**
     * 使用存储过程，完成登录的校验
     * @param user
     * @param pwd
     * @return
     */
    public boolean proCheckLogin(String user,String pwd){

        ResultSet resultSet = null;
        try {
            //3.创建调用存储过程的查询语句
            //存储过程的调用：使用callableStatement对象完成调用，调用myConnector.prepareCall("call login(?,?)")的方式
            //call login(?,?)表示存储过程需要调用两个参数 （相当于调出sql中的call login（）函数，然后再把参数传递进去）
            CallableStatement callableStatement = myConnector.prepareCall("call login(?,?)");

            //4.传递参数给存储过程，按照参数的序号进行传递 1位置就代表u  2位置就代表p
            callableStatement.setString(1,user);
            callableStatement.setString(2,pwd);

            //5.执行查询 得到结果集resultSet
            resultSet = callableStatement.executeQuery();

            //使用短路逻辑运算符，如果resultSet为空，就不会执行resultSet.next(),不会出现空指针异常
            //如果查到数据则说明登录成功，返回true
            if(resultSet!=null&&resultSet.next()){
                return true;
            }
            //否则登录失败，返回false
            else{
                return false;
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return false;
        }
    }




    /**
     * 通过输入用户名和密码进行查询，返回查询到的所有结果
     * @param user
     * @param pwd
     * @return   返回查询到的所有结果，返回格式：List<Map<String,String>> 每个map就是一行数据
     * @throws SQLException
     */
    public List<Map<String,String>> queryResult(String user,String pwd) throws SQLException {
        //3.创建查询
        Statement ggStatement = myConnector.createStatement();
        //4.编写查询语句
        String sql="select * from userinfo where username='"+user+"' and pwd='"+pwd+"'";
        //5.执行查询，得到结果集
        ResultSet resultSet = ggStatement.executeQuery(sql);
        //获取表头信息,方便遍历每一列内容
        ResultSetMetaData thead = resultSet.getMetaData();

        //查询到的数据不止一条？怎么办？
        //使用一共list，把所有的map都存起来
        List<Map<String,String>> resultList=new ArrayList<>();

        //使用循环，读取resultSet中的每一行，通过next()取值
        //resultSet.next()有值，才进行操作
        while (resultSet.next()){
            //循环中，每获取一次数据，创建一个新的map来存这一行的值
            //一行的信息存储到map中
            Map<String,String> resultMap=new HashMap<>();

            //遍历表头信息的每一列，获取列名和值 (thead.getColumnCount()一共有多少列，那么就会有长度)
            for (int column=1;column<=thead.getColumnCount();column++){
                resultMap.put(thead.getColumnName(column),resultSet.getString(column));
                System.out.println("第"+column+"列的字段是"+thead.getColumnName(column)+"内容是"+resultSet.getString(column));
            }
            //将每一行的数据map存储到List里面
            resultList.add(resultMap);

        }
        return resultList;
    }


    /**
     * 查询已经登录的用户的数据，默认只有一条
     * @param user
     * @return
     * @throws SQLException
     */
    public Map<String,String> getUserInfo(String user) {
        try {
            //3.创建查询
            Statement ggStatement = myConnector.createStatement();
            //4.编写查询语句
            String sql="select * from userinfo where username='"+user+"'";
            //5.执行查询，得到结果集
            ResultSet resultSet = ggStatement.executeQuery(sql);
            //获取表头信息,方便遍历每一列内容
            ResultSetMetaData thead = resultSet.getMetaData();
            Map<String,String> resultMap=new HashMap<>();

            //使用循环，读取resultSet中的每一行，通过next()取值
            //resultSet.next()有值，才进行操作
            while (resultSet.next()){
                //遍历表头信息的每一列，获取列名和值 (thead.getColumnCount()一共有多少列，那么就会有长度)
                for (int column=1;column<=thead.getColumnCount();column++){
                    resultMap.put(thead.getColumnName(column),resultSet.getString(column));
                }
            }
            return resultMap;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return null;
        }
    }



}
